﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using Interfaces;
using System.Threading;
using System.Runtime.InteropServices;
using OpenNETCF.Net.NetworkInformation;

namespace Wifi
{
    public class Wifi : IWifiOriginator
    {
        ctlMain mainInterface = new ctlMain();

        public System.Windows.Forms.UserControl MainInterface
        {
            get { return mainInterface; }
        }

        public string Name
        {
            get { return "WiFi"; }
        }

        CustomControls.AlphaImage IModule.IconEnabled
        {
            get { return CustomControls.AlphaImage.CreateFromResource("Wifi.Resources.status-wifi-active.png"); }
        }

        CustomControls.AlphaImage IModule.IconDisabled
        {
            get { return CustomControls.AlphaImage.CreateFromResource("Wifi.Resources.status-wifi-inactive.png"); }
        }

        public bool Sleep()
        {
            throw new NotImplementedException();
        }

        public bool Wake()
        {
            throw new NotImplementedException();
        }

        private System.Windows.Forms.Timer wifiTimer = new System.Windows.Forms.Timer();
      //  private WifiData[] nearbyAPs = new WifiData[1];
        private List<WifiData> nearbyAPs =new List<WifiData>();
     //  private List<WifiData> tempAPs = new List<WifiData>();
        private WifiData[] tempAPs = new WifiData[0];
        private WirelessZeroConfigNetworkInterface m_wzc = null;

        private IPositionHandler host;
        private bool DataValid = false;
        private System.Windows.Forms.Timer DataRequestTimer;
        private System.Windows.Forms.Timer DataValidTimer;
        private System.Windows.Forms.Timer OnOffTimer = new System.Windows.Forms.Timer();
        public class CellSignal
        {
            public string Name {get; set;}
            public int Signal {get; set;}
        }
        private List<CellSignal> BestSignals = new  List<CellSignal>();

        public int Rate
        {
            get
            {
                return wifiTimer.Interval;
            }
            set
            {
                wifiTimer.Interval = value;
            }
        }
        public int DataRequestInterval
        {
            get
            {
                return DataRequestTimer.Interval;
            }
            set
            {
                DataRequestTimer.Interval = value;
            }
        }
        public int DataValidInterval
        {
            get
            {
                return DataValidTimer.Interval;
            }
            set
            {
                DataValidTimer.Interval = value;
            }
        }

       // private AdapterCollection adapters;

        public Wifi()
        {
            wifiTimer.Interval = 5000;
            wifiTimer.Tick +=new EventHandler(wifiTimer_Tick);
            DataRequestTimer = new System.Windows.Forms.Timer();
            DataValidTimer = new System.Windows.Forms.Timer();
            DataRequestInterval = 20000;
            DataRequestTimer.Tick += new EventHandler(DataRequestTimer_Tick);
            DataValidInterval = 20000;
            DataValidTimer.Tick += new EventHandler(DataValidTimer_Tick);
            FindWirelessAdapter();
            OnOffTimer.Tick += new EventHandler(OnOffTimer_Tick);
            UpdateAPs();
            
        }

        void OnOffTimer_Tick(object sender, EventArgs e)
        {
            OnOffTimer.Enabled = false;
            if (wifiTimer.Enabled)
                SetRadioOff();
            else
                SetRadioOn();
        }

        void DataRequestTimer_Tick(object sender, EventArgs e)//ha ez üt be akkor nem jött adat a megadott várakozási idő letöltéig és ilyenkor null-t adunk vissza
        {
            DataRequestTimer.Enabled = false;
            OnRequestedDataAvailable(new PositionEventArgs(null));
         //   RequestedDataAvailable(this, EventArgs.Empty , null);

        }
        void DataValidTimer_Tick(object sender, EventArgs e)//ha ez beüt, akkor ezalatt az idő alatt nem jött új adat és így a bent lévő adat már nem érvényes
        {
            DataValidTimer.Enabled = false;

            UpdateDataValid(DataValidTimer.Enabled);

        }
        /// <summary>
        /// Jelenleg időfüggés alapján érvényes az adat, de később bővíthető ebben a függvényben
        /// </summary>
        /// <param name="valid"></param>
        private void UpdateDataValid(bool valid)
        {
            DataValid = valid;
        }
        private void wifiTimer_Tick(object sender, EventArgs e)
        {
            UpdateAPs();
        }

        private void FindWirelessAdapter()
        {
            foreach (INetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
            {
                if (ni is WirelessNetworkInterface)
                {
                    if (ni is WirelessZeroConfigNetworkInterface)
                    {
                        m_wzc = ni as WirelessZeroConfigNetworkInterface;
                    }
                    break;
                }
            }
        }
        private void UpdateAPs()
        {

            if (m_wzc == null) return;
            
            //tempAPs = nearbyAPs;
            List<WifiData> bestAPs =new List<WifiData>();
            List<WifiData> newAPs = new List<WifiData>();
            List<CellSignal> newBestSignals = new  List<CellSignal>();

            bool finditem=false;

            nearbyAPs.Clear();
            foreach (OpenNETCF.Net.NetworkInformation.AccessPoint ap in m_wzc.NearbyAccessPoints)
            {
                WifiData wd = new WifiData();
                wd.MacAddress = ap.PhysicalAddress.GetAddressBytes();
                wd.Name = ap.Name;
                wd.Rssi = ap.SignalStrength.Decibels;
                nearbyAPs.Add(wd);
                
            }


            if (nearbyAPs.Count > 0)
            {

                if (BestSignals.Count != 0)
                {
                    foreach (WifiData AP in nearbyAPs)
                    {
                        foreach (CellSignal CS in BestSignals)
                        {
                            if (CS.Name == AP.Name)
                            {
                                finditem = true;
                                if (AP.Rssi > CS.Signal)
                                {


                                    CS.Signal = AP.Rssi;
                                    newBestSignals.Add(CS);
                                    bestAPs.Add(AP);
                                }
                            }
                        }
                        if (!finditem)
                        {
                            CellSignal newitem = new CellSignal();
                            newitem.Name = AP.Name;
                            newitem.Signal = AP.Rssi;
                            newBestSignals.Add(newitem);
                        }
                    }
                    if (bestAPs.Count > 0)
                        OnBestSignal(new PositionEventArgs(bestAPs.ToArray()));
                }
                else
                {
                    foreach (WifiData AP in nearbyAPs)
                    {
                        CellSignal newitem = new CellSignal();
                        newitem.Name = AP.Name;
                        newitem.Signal = AP.Rssi;
                        newBestSignals.Add(newitem);
                    }
                }

                
                if (tempAPs.Length > 0)
                {
                    bool foundold = false;
                    //  WifiData foundednewAP = new WifiData();
                    foreach (WifiData newap in tempAPs)
                    {

                        foreach (WifiData oldap in nearbyAPs) //megkeresi, hogy az előző körben volt-e ilyen AP
                        {
                            if (newap.Name == oldap.Name) //ha volt már régebben is ilyen ap, akkor csak jelerősségösszehasonlítást végez
                            {
                                foundold = true;

                            }
                        }
                        if (!foundold)  //ha nem volt régebben ilyen ap akkor majd elsütjük újnak, de nem most, mert várunk hátha van még új több is
                            newAPs.Add(newap);
                        else
                            foundold = false;

                    }
                    if (newAPs.Count > 0)
                        OnNewSignal(new PositionEventArgs(newAPs.ToArray()));
                    
                }
                else //ha a tempbe nem voltak elemek, de most vannak szomszédok akkor azok mind újak.
                {
                    OnNewSignal(new PositionEventArgs(nearbyAPs.ToArray()));

                }
            }
            BestSignals.Clear();
            if (newBestSignals.Count > 0)
            {
                foreach (CellSignal item in newBestSignals)
                {
                    BestSignals.Add(item);

                }
            }
            
               if (DataValidTimer.Enabled)                 //ez azért kell, mert a timer úgy indul újra  0tól ha előtte le volt tiltva és Az Enabledet True-ra állítjuk
                DataValidTimer.Enabled = false;
            DataValidTimer.Enabled = true;
            UpdateDataValid(DataValidTimer.Enabled);//Az adat érvényességét állítjuk be
            if (DataRequestTimer.Enabled)//ha kértek adatot akkor visszaküldjuk a frissen beérkező adatot
            {
                DataRequestTimer.Enabled = false;
                OnRequestedDataAvailable(new PositionEventArgs(nearbyAPs.ToArray()));
                //RequestedDataAvailable(this, EventArgs.Empty, nearbyAPs.ToArray());

            }
            tempAPs = nearbyAPs.ToArray(); //elmentjük az aktuális AP-ket, hogy következő körben tudjuk vizsgálni a változást.
           // if (nearbyAPs != tempAPs)
           // {
            //    OnNewSignal(new PositionEventArgs(nearbyAPs.ToArray()));  
            //}
        }
        public bool GetRadioStatus()
        {
            return wifiTimer.Enabled;
        }
        public int SetRadioOn()
        {
            try
            {
                wifiTimer.Enabled = true;
                FindWirelessAdapter();
                OnRadioSwitchedOn(EventArgs.Empty);
            }
            catch
            {
                return 1;
            }
            return 0;
        }
        public int SetRadioOff()
        {
            try
            {
               wifiTimer.Enabled = false;
               OnRadioSwitchedOff(EventArgs.Empty);
            }
            catch
            {
                return 1;
            }
            return 0;
        }
        public int SetRadioOn(int interval)
        {
            try
            {
                if (OnOffTimer.Enabled)
                    OnOffTimer.Enabled = false;
                OnOffTimer.Interval = interval * 1000;
                if (!wifiTimer.Enabled)
                    SetRadioOn();
                OnOffTimer.Enabled = true;
            }
             
            catch
            {
                return 1;
            }
            return 0;


        }
        public int SetRadioOff(int interval)
        {
            try
            {
                if (OnOffTimer.Enabled)
                    OnOffTimer.Enabled = false;
                OnOffTimer.Interval = interval * 1000;
                if (wifiTimer.Enabled)
                    SetRadioOff();
                OnOffTimer.Enabled = true;
            }

            catch
            {
                return 1;
            }
            return 0;
        }
        
        public int DataRequest()
        {
            try
            {
                if (DataValid)//Ha érvényes az adat akkor egyből küldjük
                {

                    OnRequestedDataAvailable(new PositionEventArgs(nearbyAPs.ToArray()));
                    //RequestedDataAvailable(this, EventArgs.Empty, nearbyAPs.ToArray());
                }
                else//ha nem akkor indul a timer, ha beüt akkor null-t küldünk vissza
                {
                    // DataRequestTimer = new System.Windows.Forms.Timer();
                    if (DataRequestTimer.Enabled) //ez azért kell, mert a timer úgy indul újra  0tól ha előtte le volt tiltva és Az Enabledet True-ra állítjuk
                        DataRequestTimer.Enabled = false;
                    DataRequestTimer.Enabled = true;


                }
                return 0;
            }
            catch (Exception)
            {

                return 1;
            }
        }
        public WifiData[] GetData()
        {

            return nearbyAPs.ToArray();
        }

        #region IProximityOriginator Members

        #endregion

        #region IProximityOriginator Members

        public List<string> GetCurrentContextHashes()
        {
            List<string> temp = new List<string>();
            foreach (WifiData item in nearbyAPs)
            {
                temp.Add(item.HashValue);
            }
            return temp;
        }

        public List<IProximityData> GetCurrentContextMembers()
        {
            throw new NotImplementedException();
        }

        #endregion

        #region IPositionOriginator Members

        public new PositionOriginator GetType() //TODO: Rename this method so it doesn't hide Object.GetType
        {
            return PositionOriginator.Wifi;
        }

        #endregion

        #region IPositionOriginator Members

        public IPositionHandler Host
        {
	      get 
	      { 
		    return host;
	      }
	      set 
	      {
            host = value;
	      }
        }

        public void Initialize()
        {
            Console.WriteLine("Wifi module initialized.");
        }

        #endregion

        #region IProximityOriginator Members

        public event BestSignalEventHandler BestSignalEvent;
        public event NewSignalEventHandler NewSignalEvent;

        #endregion

        #region IPositionOriginator Members

        public void OnNewSignal(PositionEventArgs e)
        {
            if (NewSignalEvent != null)
                NewSignalEvent(this, e);
        }

        public void OnBestSignal(PositionEventArgs e)
        {
            if (BestSignalEvent != null)
                BestSignalEvent(this, e);
        }

        #endregion

        #region IPositionOriginator Members


        public void OnRadioSwitchedOff(EventArgs e)
        {
            if (RadioSwitchedOffEvent != null)
                RadioSwitchedOffEvent(this, e);
        }

        public void OnRadioSwitchedOn(EventArgs e)
        {

            if (RadioSwitchedOnEvent != null)
                RadioSwitchedOnEvent(this, e);
        }

        public void OnRequestedDataAvailable(PositionEventArgs e)
        {
            if (RequestedDataAvailable != null)
                RequestedDataAvailable(this, e);
        }

        public event RequestedDataAvailableHandler RequestedDataAvailable;

        public event RadioSwitchedOffEventHandler RadioSwitchedOffEvent;

        public event RadioSwitchedOnEventHandler RadioSwitchedOnEvent;

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}
